﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using LimaLims.Application.Service.Base.Dto;
using LimaLims.Application.Service.Basic.Dto;
using LimaLims.Application.Service.Role;
using LimaLims.Application.Service.Sys;
using LimaLims.Core;
using LimaLims.Core.Entity.Basic;
using LimaLims.Core.Enum;
using LimaLims.Core.Util;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yitter.IdGenerator;

namespace LimaLims.Application.Service.Basic
{
    /// <summary>
    /// 试验项目服务
    /// </summary>
    [ApiDescriptionSettings(Name = "InspectionItem", Order = 153)]
    [Route("api")]
    public class InspectionItemService : IInspectionItemService, IDynamicApiController, ITransient
    {
        private readonly IRepository<InspectionItem> _inspectionItemRep;  // 设备仪器表仓储
        private readonly IGenerateCodeUtilService _generateCodeUtilService;
        public InspectionItemService(IRepository<InspectionItem> inspectionItemRep, IGenerateCodeUtilService generateCodeUtilService)
        {
            _inspectionItemRep = inspectionItemRep;
            _generateCodeUtilService = generateCodeUtilService;
        }

        /// <summary>
        /// 新增
        /// </summary>
        [HttpPost("inspectionItem/add")]
        public async Task Add(AddInspectionItemInput input)
        {
            var isExist = await _inspectionItemRep.DetachedEntities.AnyAsync(u => u.InspectionName == input.InspectionName && u.Code == input.Code);
            if (isExist)
                throw Oops.Oh("已存在相同名称或者编号的试验项目");
            if (string.IsNullOrWhiteSpace(input.Code))
            {
                input.Code = await _generateCodeUtilService.GenerateCode(BusinessType.InspectionItem);
            }
            var inspectionItem = input.Adapt<InspectionItem>();

            await inspectionItem.InsertAsync();
        }

        /// <summary>
        /// 批量新增
        /// </summary>
        [HttpPost("inspectionItem/batch")]
        [UnitOfWork]
        public async Task Batch(BatchInspectionItemInput input)
        {
            List<InspectionItem> list = new List<InspectionItem>();

            foreach (var item in input.InspectionItems)
            {
                var isExist = await _inspectionItemRep.DetachedEntities.AnyAsync(u => u.InspectionName == item.InspectionName && u.Code == item.Code);
                if (isExist)
                    throw Oops.Oh("已存在相同名称或者编号的试验项目");
                if (string.IsNullOrWhiteSpace(item.Code))
                {
                    item.Code = await _generateCodeUtilService.GenerateCode(BusinessType.InspectionItem);
                }
                item.Id = YitIdHelper.NextId();
                item.InspectionType = input.InspectionType;

                var inspectionItem = item.Adapt<InspectionItem>();

                list.Add(inspectionItem);
            }

            await _inspectionItemRep.InsertAsync(list);
        }

        /// <summary>
        /// 删除
        /// </summary>
        [HttpPost("inspectionItem/delete")]
        public async Task Delete(long id)
        {
            var inspectionItem = await _inspectionItemRep.FirstOrDefaultAsync(u => u.Id == id);
            if (inspectionItem == null)
                throw Oops.Oh("不存在此数据");

            await inspectionItem.DeleteAsync();
        }

        /// <summary>
        /// 编辑
        /// </summary>
        [HttpPost("inspectionItem/edit")]
        public async Task Edit(EditInspectionItemInput input)
        {
            var inspectionItem = await _inspectionItemRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (inspectionItem == null)
                throw Oops.Oh("不存在此数据！");

            var isExist = await _inspectionItemRep.DetachedEntities.AnyAsync(u => u.InspectionName == input.InspectionName && u.Code == input.Code && u.Id != input.Id);
            if (isExist)
                throw Oops.Oh("已存在相同名称或者编号的试验项目");

            var model = input.Adapt<InspectionItem>();

            await model.UpdateAsync();
        }

        /// <summary>
        /// 详细信息
        /// </summary>
        [HttpGet("inspectionItem/detail")]
        public async Task<InspectionItem> Detail(long id)
        {
            var inspectionItem = await _inspectionItemRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == id);
            if (inspectionItem == null)
                throw Oops.Oh("不存在此数据！");
            return inspectionItem;
        }

        /// <summary>
        /// 下拉数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("inspectionItem/selectList")]
        public async Task<List<SelectDto>> SelectList(InspectionType type)
        {
            var list = await _inspectionItemRep.DetachedEntities.Where(s => s.InspectionType == type && s.ValidStatus).OrderBy(s => s.Sort).ToListAsync();
            return list.Select(x => new SelectDto
            {
                Value = x.Id,
                Label = x.InspectionName
            }).ToList();
        }

        /// <summary>
        /// 根据类型获取集合
        /// </summary>
        /// <returns></returns>
        [HttpGet("inspectionItem/getList")]
        public async Task<List<InspectionItemOutput>> GetList(InspectionType type)
        {
            var list = await _inspectionItemRep.DetachedEntities.Where(s => s.InspectionType == type && s.ValidStatus).OrderBy(s => s.Sort).ToListAsync();
            return list.Select(u => new InspectionItemOutput
            {
                Id = u.Id,
                Code = u.Code,
                InspectionName = u.InspectionName,
                InspectionType = u.InspectionType,
                Remark = u.Remark,
                NsTargetValue = u.NsTargetValue,
                NsLowerLimit = u.NsLowerLimit,
                NsUpperLimit = u.NsUpperLimit,
            }).ToList();
        }

        /// <summary>
        /// 分页数据
        /// </summary>
        [HttpGet("inspectionItem/page")]
        public async Task<PageResult<InspectionItemOutput>> QueryPage([FromQuery] InspectionItemPageInput input)
        {
            var name = !string.IsNullOrEmpty(input.SearchValue?.Trim());
            var inspectionItems = await _inspectionItemRep.DetachedEntities
                                         .Where((name, u => EF.Functions.Like(u.InspectionName, $"%{input.SearchValue.Trim()}%")|| EF.Functions.Like(u.Code, $"%{input.SearchValue.Trim()}%")))
                                         .Where(input.InspectionType.HasValue, u => u.InspectionType == input.InspectionType)
                                         .Where(input.ValidStatus.HasValue, u => u.ValidStatus == input.ValidStatus)
                                         .OrderByDescending(u => u.CreatedTime)
                                         .Select(u => new InspectionItemOutput
                                         {
                                             Id = u.Id,
                                             Code = u.Code,
                                             InspectionName = u.InspectionName,
                                             InspectionType = u.InspectionType,
                                             Remark = u.Remark,
                                             NsTargetValue = u.NsTargetValue,
                                             NsLowerLimit = u.NsLowerLimit,
                                             NsUpperLimit = u.NsUpperLimit,
                                             ValidStatus = u.ValidStatus,
                                             Sort = u.Sort,
                                             CreatedTime = u.CreatedTime,
                                             CreatedUserName = u.CreatedUserName,
                                             UpdatedTime = u.UpdatedTime,
                                             UpdatedUserName = u.UpdatedUserName
                                         }).ToADPagedListAsync(input.PageNo, input.PageSize);

            return inspectionItems;
        }
    }
}
